import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Scanner;
import java.util.Calendar;

public class CinemaSystem {
    private List<User> users = new ArrayList<>();
    private List<Movie> movies = new ArrayList<>();
    private List<Hall> halls = new ArrayList<>();
    private List<Show> shows = new ArrayList<>();
    private User currentUser;
    private SalesReport salesReport = new SalesReport();

    public CinemaSystem() {
        initData();
    }

    private void initData() {
        // 从文件读取数据
        users = FileUtil.readUsers();
        movies = FileUtil.readMovies();
        halls = FileUtil.readHalls();
        shows = FileUtil.readShows(movies, halls);

        // 如果没有数据，初始化默认数据
        if (users.isEmpty()) {
            // 默认管理员密码"ynuinfo#777"加密后存储
            users.add(new Admin("admin001", "admin",
                    MD5Util.encrypt("ynuinfo#777"), "13800138000"));
        }

        if (halls.isEmpty()) {
            halls.add(new Hall("h1", "黄金厅", 8, 10));
            halls.add(new Hall("h2", "白银厅", 10, 12));
            halls.add(new Hall("h3", "翡翠厅", 7, 8));
            halls.add(new Hall("h4", "钻石厅", 7, 8));
            halls.add(new Hall("h5", "宝石厅", 8, 9));
        }

        if (movies.isEmpty()) {
            movies.add(new Movie("m1", "复仇者联盟4", "安东尼·罗素",
                    "小罗伯特·唐尼,克里斯·埃文斯", "漫威超级英雄电影", 181, 8.5));
            movies.add(new Movie("m2", "流浪地球2", "郭帆",
                    "吴京,李雪健", "科幻灾难电影", 173, 8.3));
        }
    }

    // 保存数据到文件
    private void saveData() {
        FileUtil.writeUsers(users);
        FileUtil.writeMovies(movies);
        FileUtil.writeHalls(halls);
        FileUtil.writeShows(shows);
        System.out.println("数据已保存");
    }

    public void start() {
        Scanner scanner = new Scanner(System.in);
        try {
            while (true) {
                if (currentUser == null) {
                    showLoginMenu(scanner);
                } else {
                    if (currentUser instanceof Admin) {
                        showAdminMenu(scanner);
                    } else if (currentUser instanceof Manager) {
                        showManagerMenu(scanner);
                    } else if (currentUser instanceof FrontDesk) {
                        showFrontMenu(scanner);
                    }
                }
            }
        } finally {
            scanner.close();
        }
    }

    private void showLoginMenu(Scanner scanner) {
        System.out.println("\n=== 影院管理系统 ===");
        System.out.println("1. 登录");
        System.out.println("2. 退出");
        System.out.print("请选择: ");
        int choice = getValidInt(scanner, 1, 2);
        if (choice == 1) {
            login(scanner);
        } else {
            saveData(); // 退出时保存数据
            System.out.println("感谢使用影院管理系统，再见！");
            System.exit(0);
        }
    }

    private void login(Scanner scanner) {
        System.out.print("用户名: ");
        String username = scanner.nextLine();
        System.out.print("密码: ");
        String password = scanner.nextLine();
        // 密码加密后验证
        String encryptedPwd = MD5Util.encrypt(password);

        for (User user : users) {
            if (user.getUsername().equals(username) && user.login(encryptedPwd)) {
                currentUser = user;
                System.out.println("登录成功，欢迎" + user.getUserType() + "[" + username + "]");
                return;
            }
        }
        System.out.println("用户名或密码错误");
    }

    private void showAdminMenu(Scanner scanner) {
        System.out.println("\n=== 管理员菜单 ===");
        System.out.println("1. 添加用户");
        System.out.println("2. 删除用户");
        System.out.println("3. 重置用户密码");
        System.out.println("4. 查看所有用户");
        System.out.println("5. 查看销售报表");
        System.out.println("6. 退出登录");
        System.out.print("请选择: ");

        int choice = getValidInt(scanner, 1, 6);
        switch (choice) {
            case 1:
                addUser(scanner);
                break;
            case 2:
                deleteUser(scanner);
                break;
            case 3:
                resetPassword(scanner);
                break;
            case 4:
                viewAllUsers();
                break;
            case 5:
                viewSalesReport(scanner);
                break;
            case 6:
                currentUser = null;
                System.out.println("已退出登录");
                break;
        }
    }

    private void addUser(Scanner scanner) {
        System.out.println("\n=== 添加用户 ===");
        System.out.println("1. 添加管理员");
        System.out.println("2. 添加经理");
        System.out.println("3. 添加前台");
        System.out.print("请选择用户类型: ");
        int type = getValidInt(scanner, 1, 3);

        System.out.print("用户ID: ");
        String id = scanner.nextLine();
        System.out.print("用户名: ");
        String username = scanner.nextLine();
        System.out.print("密码: ");
        String password = scanner.nextLine();
        // 密码加密处理
        String encryptedPwd = MD5Util.encrypt(password);
        System.out.print("手机号: ");
        String phone = scanner.nextLine();

        User newUser = switch (type) {
            case 1 -> new Admin(id, username, encryptedPwd, phone);
            case 2 -> new Manager(id, username, encryptedPwd, phone);
            case 3 -> new FrontDesk(id, username, encryptedPwd, phone);
            default -> null;
        };

        try {
            ((Admin) currentUser).addUser(newUser, users);
            System.out.println("成功添加" + newUser.getUserType() + "[" + username + "]");
        } catch (IllegalArgumentException e) {
            System.out.println("添加失败: " + e.getMessage());
        }
    }

    private void deleteUser(Scanner scanner) {
        System.out.println("\n=== 删除用户 ===");
        System.out.print("请输入要删除的用户ID: ");
        String userId = scanner.nextLine();

        try {
            ((Admin) currentUser).deleteUser(userId, users);
            System.out.println("用户删除成功");
        } catch (IllegalArgumentException e) {
            System.out.println("删除失败: " + e.getMessage());
        }
    }

    private void resetPassword(Scanner scanner) {
        System.out.print("\n请输入要重置密码的用户ID: ");
        String userId = scanner.nextLine();

        User targetUser = users.stream()
                .filter(u -> u.getId().equals(userId))
                .findFirst().orElse(null);

        if (targetUser == null) {
            System.out.println("用户不存在");
            return;
        }

        // 重置密码为"123456"并加密
        ((Admin) currentUser).resetPassword(targetUser);
        System.out.println("已重置用户[" + targetUser.getUsername() + "]的密码为: 123456");
    }

    private void viewAllUsers() {
        System.out.println("\n=== 所有用户列表 ===");
        System.out.println("ID\t用户名\t类型\t电话\t注册时间\t状态");
        System.out.println("------------------------------------------------");

        for (User user : users) {
            // 修复：使用isLocked()方法替代直接访问locked字段
            String status = user.isLocked() ? "已锁定" : "正常";
            System.out.printf("%s\t%s\t%s\t%s\t%s\t%s%n",
                    user.getId(),
                    user.getUsername(),
                    user.getUserType(),
                    user.getPhone(),
                    DateUtil.format(user.getRegisterTime()),
                    status);
        }
    }

    private void viewSalesReport(Scanner scanner) {
        System.out.println("\n=== 销售报表 ===");
        System.out.println("1. 今日销售报表");
        System.out.println("2. 本周销售报表");
        System.out.println("3. 本月销售报表");
        System.out.print("请选择: ");

        int choice = getValidInt(scanner, 1, 3);
        switch (choice) {
            case 1:
                salesReport.dailyReport(shows);
                break;
            case 2:
                salesReport.weeklyReport(shows);
                break;
            case 3:
                salesReport.monthlyReport(shows);
                break;
        }
    }

    private void showManagerMenu(Scanner scanner) {
        System.out.println("\n=== 经理菜单 ===");
        System.out.println("1. 添加电影");
        System.out.println("2. 查看所有电影");
        System.out.println("3. 添加场次");
        System.out.println("4. 修改场次");
        System.out.println("5. 查看所有场次");
        System.out.println("6. 查看销售报表");
        System.out.println("7. 退出登录");
        System.out.print("请选择: ");

        int choice = getValidInt(scanner, 1, 7);
        switch (choice) {
            case 1:
                addMovie(scanner);
                break;
            case 2:
                viewAllMovies();
                break;
            case 3:
                addShow(scanner);
                break;
            case 4:
                updateShow(scanner);
                break;
            case 5:
                viewAllShows();
                break;
            case 6:
                viewSalesReport(scanner);
                break;
            case 7:
                currentUser = null;
                System.out.println("已退出登录");
                break;
        }
    }

    private void addMovie(Scanner scanner) {
        System.out.println("\n=== 添加电影 ===");
        System.out.print("电影ID: ");
        String id = scanner.nextLine();
        System.out.print("电影名称: ");
        String name = scanner.nextLine();
        System.out.print("导演: ");
        String director = scanner.nextLine();
        System.out.print("主演(用逗号分隔): ");
        String actors = scanner.nextLine();
        System.out.print("电影简介: ");
        String introduction = scanner.nextLine();
        System.out.print("电影时长(分钟): ");
        int duration = getValidInt(scanner, 60, 300);
        System.out.print("电影评分: ");
        double rating = getValidDouble(scanner, 0, 10);

        Movie movie = new Movie(id, name, director, actors, introduction, duration, rating);
        ((Manager) currentUser).addMovie(movie, movies);
        System.out.println("电影添加成功");
    }

    private void viewAllMovies() {
        System.out.println("\n=== 所有电影列表 ===");
        System.out.println("ID\t名称\t导演\t主演\t时长(分钟)\t评分");
        System.out.println("------------------------------------------------");

        for (Movie movie : movies) {
            System.out.printf("%s\t%s\t%s\t%s\t%d\t%.1f%n",
                    movie.getId(),
                    movie.getName(),
                    movie.getDirector(),
                    movie.getActors().length() > 8 ? movie.getActors().substring(0, 8) + "..." : movie.getActors(),
                    movie.getDuration(),
                    movie.getRating());
        }
    }

    private void addShow(Scanner scanner) {
        System.out.println("\n=== 添加场次 ===");

        // 显示所有电影供选择
        System.out.println("可选电影:");
        for (int i = 0; i < movies.size(); i++) {
            System.out.printf("%d. %s (%s)%n", i+1, movies.get(i).getName(), movies.get(i).getId());
        }
        System.out.print("请选择电影(编号): ");
        int movieIndex = getValidInt(scanner, 1, movies.size()) - 1;
        Movie selectedMovie = movies.get(movieIndex);

        // 显示所有放映厅供选择
        System.out.println("\n可选放映厅:");
        for (int i = 0; i < halls.size(); i++) {
            System.out.printf("%d. %s (%s, %d行%d列)%n",
                    i+1, halls.get(i).getName(), halls.get(i).getId(),
                    halls.get(i).getRows(), halls.get(i).getCols());
        }
        System.out.print("请选择放映厅(编号): ");
        int hallIndex = getValidInt(scanner, 1, halls.size()) - 1;
        Hall selectedHall = halls.get(hallIndex);

        // 输入场次信息
        System.out.print("场次ID: ");
        String showId = scanner.nextLine();
        System.out.print("放映时间(yyyy-MM-dd HH:mm:ss): ");
        String timeStr = scanner.nextLine();
        System.out.print("票价: ");
        double price = getValidDouble(scanner, 10, 200);

        try {
            Date showTime = DateUtil.parse(timeStr);
            Show show = new Show(showId, selectedMovie, selectedHall, showTime, price);
            ((Manager) currentUser).addShow(show, shows);
            System.out.println("场次添加成功");
        } catch (IllegalArgumentException e) {
            System.out.println("添加失败: " + e.getMessage());
        }
    }

    private void updateShow(Scanner scanner) {
        System.out.println("\n=== 修改场次 ===");

        if (shows.isEmpty()) {
            System.out.println("没有场次可修改");
            return;
        }

        // 显示所有场次供选择
        System.out.println("当前场次:");
        for (int i = 0; i < shows.size(); i++) {
            Show show = shows.get(i);
            System.out.printf("%d. %s - %s - %s - ￥%.1f%n",
                    i+1, show.getShowId(), show.getMovie().getName(),  // 修复：使用getShowId()获取场次ID
                    DateUtil.format(show.getShowTime()), show.getPrice());
        }
        System.out.print("请选择要修改的场次(编号): ");
        int showIndex = getValidInt(scanner, 1, shows.size()) - 1;
        Show showToUpdate = shows.get(showIndex);

        // 输入新的场次信息
        System.out.print("新的放映时间(yyyy-MM-dd HH:mm:ss，回车保持不变): ");
        String timeStr = scanner.nextLine();
        System.out.print("新的票价(回车保持不变): ");
        String priceStr = scanner.nextLine();

        try {
            Date newTime = showToUpdate.getShowTime();
            if (!timeStr.isEmpty()) {
                newTime = DateUtil.parse(timeStr);
            }

            double newPrice = showToUpdate.getPrice();
            if (!priceStr.isEmpty()) {
                newPrice = Double.parseDouble(priceStr);
            }

            // 创建更新后的场次对象（修复：使用getShowId()获取原始ID）
            Show updatedShow = new Show(
                    showToUpdate.getShowId(),
                    showToUpdate.getMovie(),
                    showToUpdate.getHall(),
                    newTime,
                    newPrice
            );

            ((Manager) currentUser).updateShow(updatedShow, shows);
            System.out.println("场次修改成功");
        } catch (IllegalArgumentException e) {
            System.out.println("修改失败: " + e.getMessage());
        }
    }

    private void viewAllShows() {
        System.out.println("\n=== 所有场次列表 ===");
        System.out.println("ID\t电影\t放映厅\t时间\t票价");
        System.out.println("------------------------------------------------");

        for (Show show : shows) {
            System.out.printf("%s\t%s\t%s\t%s\t￥%.1f%n",
                    show.getShowId(),  // 修复：使用getShowId()获取场次ID
                    show.getMovie().getName(),
                    show.getHall().getName(),
                    DateUtil.format(show.getShowTime()),
                    show.getPrice());
        }
    }

    private void showFrontMenu(Scanner scanner) {
        System.out.println("\n=== 前台菜单 ===");
        System.out.println("1. 查看所有电影");
        System.out.println("2. 查看所有场次");
        System.out.println("3. 售票");
        System.out.println("4. 退票");
        System.out.println("5. 退出登录");
        System.out.print("请选择: ");

        int choice = getValidInt(scanner, 1, 5);
        switch (choice) {
            case 1:
                viewAllMovies();
                break;
            case 2:
                viewAllShows();
                break;
            case 3:
                sellTicket(scanner);
                break;
            case 4:
                refundTicket(scanner);
                break;
            case 5:
                currentUser = null;
                System.out.println("已退出登录");
                break;
        }
    }

    private void sellTicket(Scanner scanner) {
        System.out.println("\n=== 售票 ===");

        if (shows.isEmpty()) {
            System.out.println("没有场次可售票");
            return;
        }

        // 显示所有场次供选择
        System.out.println("可选场次:");
        for (int i = 0; i < shows.size(); i++) {
            Show show = shows.get(i);
            System.out.printf("%d. %s - %s - %s - ￥%.1f%n",
                    i+1, show.getMovie().getName(), show.getHall().getName(),
                    DateUtil.format(show.getShowTime()), show.getPrice());
        }
        System.out.print("请选择场次(编号): ");
        int showIndex = getValidInt(scanner, 1, shows.size()) - 1;
        Show selectedShow = shows.get(showIndex);

        // 显示座位情况
        System.out.println("\n座位情况 (O: 可选 X: 已售):");
        Hall hall = selectedShow.getHall();
        for (int i = 1; i <= hall.getRows(); i++) {
            StringBuilder rowStr = new StringBuilder();
            for (int j = 1; j <= hall.getCols(); j++) {
                // 修复：座位ID格式与Hall中保持一致（行-列）
                String seatId = i + "-" + j;
                boolean sold = hall.getSeats().stream()
                        .filter(s -> s.getId().equals(seatId))
                        .findFirst()
                        .map(Seat::isSold)
                        .orElse(false);
                rowStr.append(sold ? "X " : "O ");
            }
            System.out.println("第" + i + "行: " + rowStr);
        }

        // 选择座位
        System.out.print("请输入要购买的座位号(如:1-1 1-2 表示1行1列和1行2列，用空格分隔): ");
        String[] seatPositions = scanner.nextLine().split(" ");
        List<String> seatIds = new ArrayList<>();

        for (String pos : seatPositions) {
            if (pos.trim().isEmpty()) continue;
            // 修复：座位格式改为"行-列"（与Hall中一致）
            String[] coords = pos.split("-");
            if (coords.length != 2) {
                System.out.println("座位格式错误: " + pos + "，正确格式为行-列（如1-1）");
                return;
            }
            try {
                int row = Integer.parseInt(coords[0]);
                int col = Integer.parseInt(coords[1]);
                if (row < 1 || row > hall.getRows() || col < 1 || col > hall.getCols()) {
                    System.out.println("座位不存在: " + pos);
                    return;
                }
                seatIds.add(row + "-" + col);  // 修复：统一座位ID格式
            } catch (NumberFormatException e) {
                System.out.println("座位格式错误: " + pos);
                return;
            }
        }

        if (seatIds.isEmpty()) {
            System.out.println("未选择任何座位");
            return;
        }

        // 输入顾客信息
        System.out.print("请输入顾客手机号: ");
        String phone = scanner.nextLine();

        try {
            Ticket ticket = ((FrontDesk) currentUser).sellTicket(selectedShow, seatIds, phone);
            System.out.println("\n售票成功!");
            System.out.println("票号: " + ticket.getId());
            System.out.println("电影: " + selectedShow.getMovie().getName());
            System.out.println("场次: " + DateUtil.format(selectedShow.getShowTime()));
            System.out.println("放映厅: " + selectedShow.getHall().getName());
            System.out.println("座位: " + String.join(", ", seatIds));
            System.out.println("总价: ￥" + (ticket.getPrice() * seatIds.size()));
        } catch (IllegalArgumentException e) {
            System.out.println("售票失败: " + e.getMessage());
        }
    }

    private void refundTicket(Scanner scanner) {
        System.out.println("\n=== 退票 ===");
        System.out.print("请输入要退的票号: ");
        String ticketId = scanner.nextLine();

        // 查找票是否存在
        Ticket ticketToRefund = null;
        for (Show show : shows) {
            for (Ticket t : show.getTickets()) {
                if (t.getId().equals(ticketId)) {
                    ticketToRefund = t;
                    break;
                }
            }
            if (ticketToRefund != null) break;
        }

        if (ticketToRefund == null) {
            System.out.println("票不存在");
            return;
        }

        try {
            ((FrontDesk) currentUser).refundTicket(ticketId, shows);
            System.out.println("退票成功");
        } catch (IllegalArgumentException e) {
            System.out.println("退票失败: " + e.getMessage());
        }
    }

    private int getValidInt(Scanner scanner, int min, int max) {
        while (true) {
            try {
                int num = Integer.parseInt(scanner.nextLine());
                if (num >= min && num <= max) return num;
                System.out.printf("请输入%d-%d之间的数字: ", min, max);
            } catch (NumberFormatException e) {
                System.out.print("输入无效，请重新输入: ");
            }
        }
    }

    private double getValidDouble(Scanner scanner, double min, double max) {
        while (true) {
            try {
                double num = Double.parseDouble(scanner.nextLine());
                if (num >= min && num <= max) return num;
                System.out.printf("请输入%.1f-%.1f之间的数字: ", min, max);
            } catch (NumberFormatException e) {
                System.out.print("输入无效，请重新输入: ");
            }
        }
    }
}